package it.polimi.TravelDream;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 * Session Bean implementation class PackageMgrBean
 */
@Stateless
public class PackageMgrBean implements PackageMgr {

    /**
     * Default constructor. 
     */

	@PersistenceContext
    private  EntityManager em;
	
	@Resource
	private EJBContext context;
	
    public User getCurrentUser() {
    	return em.createNamedQuery(User.GetCurrent, User.class)
    			.setParameter("param", context.getCallerPrincipal().getName())
                .getSingleResult();
    }


	@Override
	public void saveBasePackage(BasePackageDTO basePackageDTO,List<ExcursionDTO> excursionlist) {
		
		Basepackage newbasePackage = new Basepackage();
		newbasePackage.setArrDate(basePackageDTO.getDepDate());
		newbasePackage.setDepDate(basePackageDTO.getRetDate());
		newbasePackage.setArrLocation(basePackageDTO.getArrLocation());
		newbasePackage.setDepLocation(basePackageDTO.getDepLocation());
		newbasePackage.setCreatedDate(new Date());
		newbasePackage.setUser(getCurrentUser());
		newbasePackage.setId(basePackageDTO.getId());
		if(basePackageDTO.getOutFlightID()==-1)
		newbasePackage.setFlight1(null);
		else
		newbasePackage.setFlight1(em.find(Flight.class, basePackageDTO.getOutFlightID()));
		if(basePackageDTO.getRetFlightID()==-1)
		newbasePackage.setFlight2(null);
		else
		newbasePackage.setFlight2(em.find(Flight.class, basePackageDTO.getRetFlightID()));
		if(basePackageDTO.getHotelID()==-1)
		newbasePackage.setHotel(null);
		else
		newbasePackage.setHotel(em.find(Hotel.class, basePackageDTO.getHotelID()));
		em.persist(newbasePackage);
		em.flush();
		em.refresh(newbasePackage);
		for (ExcursionDTO e : excursionlist)
        {
           Basepackexlinker bpel = new Basepackexlinker();
           BasepackexlinkerPK pk = new BasepackexlinkerPK();
           pk.setExcursionID(e.getId());
           pk.setPackageID(newbasePackage.getId());
           bpel.setBasepackage(newbasePackage);
           bpel.setExcursion(em.find(Excursion.class, e.getId()));
           bpel.setId(pk);
           em.persist(bpel);
        }
		
	}

public void updateBasePackage(BasePackageDTO basePackageDTO,List<ExcursionDTO> excursionlist) {
		Basepackage newbasePackage = new Basepackage();
		newbasePackage = em.merge(em.find(Basepackage.class, basePackageDTO.getId()));
		newbasePackage.setArrDate(basePackageDTO.getDepDate());
		newbasePackage.setDepDate(basePackageDTO.getRetDate());
		newbasePackage.setArrLocation(basePackageDTO.getArrLocation());
		newbasePackage.setDepLocation(basePackageDTO.getDepLocation());
		newbasePackage.setCreatedDate(new Date());
		newbasePackage.setUser(getCurrentUser());
		newbasePackage.setId(basePackageDTO.getId());
		newbasePackage.setBasepackexlinkers(null);
		if(basePackageDTO.getOutFlightID()==-1)
		newbasePackage.setFlight1(null);
		else
		newbasePackage.setFlight1(em.find(Flight.class, basePackageDTO.getOutFlightID()));
		if(basePackageDTO.getRetFlightID()==-1)
		newbasePackage.setFlight2(null);
		else
		newbasePackage.setFlight2(em.find(Flight.class, basePackageDTO.getRetFlightID()));
		if(basePackageDTO.getHotelID()==-1)
		newbasePackage.setHotel(null);
		else
		newbasePackage.setHotel(em.find(Hotel.class, basePackageDTO.getHotelID()));
		em.flush();
		em.refresh(newbasePackage);
		em.createNamedQuery("Basepackexlinker.eliminateByPack", Basepackexlinker.class)
			.setParameter("param", newbasePackage.getId())
			.executeUpdate();
		for (ExcursionDTO e : excursionlist)
        {
           Basepackexlinker bpel = new Basepackexlinker();
           BasepackexlinkerPK pk = new BasepackexlinkerPK();
           pk.setExcursionID(e.getId());
           pk.setPackageID(newbasePackage.getId());
           bpel.setBasepackage(newbasePackage);
           bpel.setExcursion(em.find(Excursion.class, e.getId()));
           bpel.setId(pk);
           em.persist(bpel);
        }
		
	}
	
	@Override
	public void saveSavedPackage(SavedPackageDTO savedPackageDTO, List<ExcursionDTO>excursionlist){
		
		Savedpackage newsavedPackage = new Savedpackage();
		newsavedPackage.setDepDate(savedPackageDTO.getDepDate());
		newsavedPackage.setRetDate(savedPackageDTO.getRetDate());
		newsavedPackage.setArrLocation(savedPackageDTO.getArrLocation());
		newsavedPackage.setDepLocation(savedPackageDTO.getDepLocation());
		newsavedPackage.setUser(getCurrentUser());
		newsavedPackage.setId(savedPackageDTO.getId());
		newsavedPackage.setCreatorPeople(savedPackageDTO.getCreatorPeople());
		newsavedPackage.setTotPeople(savedPackageDTO.getCreatorPeople());
		newsavedPackage.setSaveDate(new Date());
		if(savedPackageDTO.getFlight1()==-1)
			newsavedPackage.setFlight1(null);
		else
			newsavedPackage.setFlight1(em.find(Flight.class, savedPackageDTO.getFlight1()));
		if(savedPackageDTO.getFlight2()==-1)
			newsavedPackage.setFlight2(null);
		else
			newsavedPackage.setFlight2(em.find(Flight.class, savedPackageDTO.getFlight2()));
		if(savedPackageDTO.getHotel()==-1)
			newsavedPackage.setHotel(null);
		else
			newsavedPackage.setHotel(em.find(Hotel.class, savedPackageDTO.getHotel()));
		em.persist(newsavedPackage);
		em.flush();
		em.refresh(newsavedPackage);
		for (ExcursionDTO e : excursionlist)
        {
           Packexlinker spel = new Packexlinker();
           PackexlinkerPK pk = new PackexlinkerPK();
           pk.setExcursionID(e.getId());
           pk.setPackageID(newsavedPackage.getId());
           spel.setSavedpackage(newsavedPackage);
           spel.setExcursion(em.find(Excursion.class, e.getId()));
           spel.setId(pk);
           em.persist(spel);
        }
		
		
		
	}
@Override	
public void updateSavedPackage(SavedPackageDTO savedPackageDTO,List<ExcursionDTO> excursionlist) {
		
		int joinedPeople = 0;
		List<Packagejoin> joinedlist = em.createNamedQuery("Packagejoin.findByPackID", Packagejoin.class)
										.setParameter("param1", savedPackageDTO.getId())
										.getResultList();
		for (Packagejoin p : joinedlist)
        {
            joinedPeople = joinedPeople + p.getJoinedPeople();
        }
		Savedpackage newsavedPackage = new Savedpackage();
		newsavedPackage = em.merge(em.find(Savedpackage.class, savedPackageDTO.getId()));
		newsavedPackage.setDepDate(savedPackageDTO.getDepDate());
		newsavedPackage.setRetDate(savedPackageDTO.getRetDate());
		newsavedPackage.setArrLocation(savedPackageDTO.getArrLocation());
		newsavedPackage.setDepLocation(savedPackageDTO.getDepLocation());
		newsavedPackage.setId(savedPackageDTO.getId());
		newsavedPackage.setCreatorPeople(savedPackageDTO.getCreatorPeople());
		newsavedPackage.setTotPeople(savedPackageDTO.getCreatorPeople() + joinedPeople);
		if(savedPackageDTO.getFlight1()==-1)
		newsavedPackage.setFlight1(null);
		else
		newsavedPackage.setFlight1(em.find(Flight.class, savedPackageDTO.getFlight1()));
		if(savedPackageDTO.getFlight2()==-1)
		newsavedPackage.setFlight2(null);
		else
		newsavedPackage.setFlight2(em.find(Flight.class, savedPackageDTO.getFlight2()));
		if(savedPackageDTO.getHotel()==-1)
		newsavedPackage.setHotel(null);
		else
		newsavedPackage.setHotel(em.find(Hotel.class, savedPackageDTO.getHotel()));
		em.flush();
		em.refresh(newsavedPackage);
		em.createNamedQuery("Packexlinker.eliminateByPack", Packexlinker.class)
		.setParameter("param", newsavedPackage.getId())
		.executeUpdate();
		for (ExcursionDTO e : excursionlist)
        {
           Packexlinker spel = new Packexlinker();
           PackexlinkerPK pk = new PackexlinkerPK();
           pk.setExcursionID(e.getId());
           pk.setPackageID(newsavedPackage.getId());
           spel.setSavedpackage(newsavedPackage);
           spel.setExcursion(em.find(Excursion.class, e.getId()));
           spel.setId(pk);
           em.persist(spel);
        }
		

	}
	
	public void deleteBasePackage(BasePackageDTO basepackage){
		em.remove(em.find(Basepackage.class, basepackage.getId()));
	}
	
	@Override
	public void deleteSavedPackage(SavedPackageDTO savedPackage){
		em.remove(em.find(Savedpackage.class, savedPackage.getId()));
	}
	
	
	 protected static BasePackageDTO convertBasePackageToDTO(Basepackage basepackage){
	    	BasePackageDTO basepackageDTO = new BasePackageDTO();
	    	basepackageDTO.setDepLocation(basepackage.getDepLocation());
	    	basepackageDTO.setArrLocation(basepackage.getArrLocation());
	    	basepackageDTO.setDepDate(basepackage.getArrDate());
	    	basepackageDTO.setRetDate(basepackage.getDepDate());
	    	basepackageDTO.setId(basepackage.getId());
	    	if (basepackage.getFlight1()==null) basepackageDTO.setOutFlightID(-1);
	    	else basepackageDTO.setOutFlightID(basepackage.getFlight1().getId());
	    	if (basepackage.getFlight2()==null) basepackageDTO.setRetFlightID(-1);
	    	else basepackageDTO.setRetFlightID(basepackage.getFlight2().getId());
	    	if (basepackage.getHotel()==null) basepackageDTO.setHotelID(-1);
	    	else basepackageDTO.setHotelID(basepackage.getHotel().getId()); 
	    	
	    	return basepackageDTO;    	
	    }
	 
	 protected static SavedPackageDTO convertSavedPackageToDTO(Savedpackage savedpackage){
		 
	    	SavedPackageDTO savedpackageDTO = new SavedPackageDTO();
	    	savedpackageDTO.setId(savedpackage.getId());
	    	savedpackageDTO.setDepLocation(savedpackage.getDepLocation());
	    	savedpackageDTO.setArrLocation(savedpackage.getArrLocation());
	    	savedpackageDTO.setDepDate(savedpackage.getDepDate());
	    	savedpackageDTO.setConfDate(savedpackage.getConfDate());
	    	savedpackageDTO.setConfirmed(savedpackage.getConfirmed());
	    	savedpackageDTO.setCreatorPeople(savedpackage.getCreatorPeople());
	    	savedpackageDTO.setHotToBeP(savedpackage.getHotToBeP());
	    	savedpackageDTO.setFlight1ToBeP(savedpackage.getOutToBeP());
	    	savedpackageDTO.setflight2ToBeP(savedpackage.getRetToBeP());
	    	savedpackageDTO.setRetDate(savedpackage.getRetDate());
	    	savedpackageDTO.setSaveDate(savedpackage.getSaveDate());
	    	savedpackageDTO.setTotPeople(savedpackage.getTotPeople());
	    	if (savedpackage.getFlight1()==null) savedpackageDTO.setFlight1(-1);
	    	else savedpackageDTO.setFlight1(savedpackage.getFlight1().getId());
	    	if (savedpackage.getFlight2()==null) savedpackageDTO.setFlight2(-1);
	    	else savedpackageDTO.setFlight2(savedpackage.getFlight2().getId());
	    	if (savedpackage.getHotel()==null) savedpackageDTO.setHotel(-1);
	    	else savedpackageDTO.setHotel(savedpackage.getHotel().getId());
	    	savedpackageDTO.setOwnerId(savedpackage.getUser().getId());
	    	return savedpackageDTO;    	
	    }
	 @Override
	 public void insertNewJoin(PackagejoinDTO packJDTO){
		 
		 Packagejoin pj = new Packagejoin();
		 pj.setJoinedPeople(packJDTO.getJoinedPeople());
		 pj.setSavedpackage(em.find(Savedpackage.class, packJDTO.getPackID()));
		 pj.setUser(em.find(User.class, packJDTO.getJoiner()));
		 PackagejoinPK packjoinPK = new PackagejoinPK();
		 packjoinPK.setIDJoiner(packJDTO.getJoiner());
		 packjoinPK.setIDPackage(packJDTO.getPackID());
		 pj.setId(packjoinPK);
		 em.persist(pj);	 
		 
	 }


	@Override
	public boolean checkIfJoined(int joinerID, int packID) {
		
		Packagejoin pj = new Packagejoin();
		PackagejoinPK packjoinPK = new PackagejoinPK();
		packjoinPK.setIDJoiner(joinerID);
		packjoinPK.setIDPackage(packID);
		pj = em.find(Packagejoin.class, packjoinPK);
		if (pj==null) return false;
		else return true;
	}


	@Override
	public void confirmSavedPackage(SavedPackageDTO savedPackage,
			List<ExcursionDTO> excList) {
		
		int joinedPeople = 0;
		List<Packagejoin> joinedlist = em.createNamedQuery("Packagejoin.findByPackID", Packagejoin.class)
										.setParameter("param1", savedPackage.getId())
										.getResultList();
		for (Packagejoin p : joinedlist)
        {
            joinedPeople = joinedPeople + p.getJoinedPeople();
        }
		Savedpackage newsavedPackage = new Savedpackage();
		newsavedPackage = em.merge(em.find(Savedpackage.class, savedPackage.getId()));
		newsavedPackage.setDepDate(savedPackage.getDepDate());
		newsavedPackage.setRetDate(savedPackage.getRetDate());
		newsavedPackage.setArrLocation(savedPackage.getArrLocation());
		newsavedPackage.setDepLocation(savedPackage.getDepLocation());
		newsavedPackage.setId(savedPackage.getId());
		newsavedPackage.setCreatorPeople(savedPackage.getCreatorPeople());
		newsavedPackage.setTotPeople(savedPackage.getCreatorPeople() + joinedPeople);
		if(savedPackage.getFlight1()!=-1)newsavedPackage.setOutToBeP(newsavedPackage.getTotPeople());
		if(savedPackage.getFlight2()!=-1)newsavedPackage.setRetToBeP(newsavedPackage.getTotPeople());
		if(savedPackage.getHotel()!=-1)newsavedPackage.setHotToBeP(newsavedPackage.getTotPeople());
		newsavedPackage.setConfirmed(true);
		newsavedPackage.setConfDate(new Date());
		if(savedPackage.getFlight1()==-1)
		newsavedPackage.setFlight1(null);
		else
		newsavedPackage.setFlight1(em.find(Flight.class, savedPackage.getFlight1()));
		if(savedPackage.getFlight2()==-1)
		newsavedPackage.setFlight2(null);
		else
		newsavedPackage.setFlight2(em.find(Flight.class, savedPackage.getFlight2()));
		if(savedPackage.getHotel()==-1)
		newsavedPackage.setHotel(null);
		else
		newsavedPackage.setHotel(em.find(Hotel.class, savedPackage.getHotel()));
		em.flush();
		em.refresh(newsavedPackage);
		em.createNamedQuery("Packexlinker.eliminateByPack", Packexlinker.class)
		.setParameter("param", newsavedPackage.getId())
		.executeUpdate();
		if (!excList.isEmpty()){
		for (ExcursionDTO e : excList)
        	{
           Packexlinker spel = new Packexlinker();
           PackexlinkerPK pk = new PackexlinkerPK();
           pk.setExcursionID(e.getId());
           pk.setPackageID(newsavedPackage.getId());
           spel.setSavedpackage(newsavedPackage);
           spel.setExcursion(em.find(Excursion.class, e.getId()));
           spel.setId(pk);
           spel.setLeftToBeP(newsavedPackage.getTotPeople());
           em.persist(spel);
        	}
		}
	}
	
	@Override
	public int searchExcToBePaid(int packID){
		int excToBePaid;
		Packexlinker spel = new Packexlinker();
		spel = em.createNamedQuery("Packexlinker.findByPack",Packexlinker.class)
				.setParameter("param", packID)
				.getResultList().get(0);
		excToBePaid = spel.getLeftToBeP();
		return excToBePaid;
		
	}


	@Override
	public void payment(SavedPackageDTO savedPackage, int totalPaied,
			String messagePayer, String namePayer,int excToBePaid) {
		
		Savedpackage newsavedPackage = new Savedpackage();
		newsavedPackage = em.merge(em.find(Savedpackage.class, savedPackage.getId()));
		if(savedPackage.getFlight1()!=-1)newsavedPackage.setOutToBeP(savedPackage.getFlight1ToBeP());
		if(savedPackage.getFlight2()!=-1)newsavedPackage.setRetToBeP(savedPackage.getflight2ToBeP());
		if(savedPackage.getHotel()!=-1)newsavedPackage.setHotToBeP(savedPackage.getHotToBeP());
		em.flush();
		List<Packexlinker> spel = em.createNamedQuery("Packexlinker.findByPack",Packexlinker.class)
				.setParameter("param", savedPackage.getId())
				.getResultList();
		for(Packexlinker p : spel){
			Packexlinker p2 = new Packexlinker();
			p2 = em.merge(em.find(Packexlinker.class, p.getId()));		
			p2.setLeftToBeP(excToBePaid);
			em.flush();
		}
		Payment paymentClass = new Payment();
		paymentClass.setNote(messagePayer);
		paymentClass.setAmount(totalPaied);
		paymentClass.setDate(new Date());
		paymentClass.setPayer(namePayer);
		paymentClass.setSavedpackage(em.find(Savedpackage.class, savedPackage.getId()));	
		em.persist(paymentClass);
	}
	


}
